using Circus.CodeEditor;
using System;
using System.Collections.Generic;
using System.Drawing;
namespace Circus.Syntax
{
	[Serializable]
	public class SyntaxNode : ICloneable
	{
		private Range range = new Range(0, 0, 0, 0);
		private string name = string.Empty;
		private SyntaxNode parent;
		private int nodeType;
		private SyntaxNodes childs;
		private SyntaxAttributes attributes;
		private SyntaxErrors errors;
		private SyntaxNodeOptions options;
		private object containsErrors;
		public virtual Range Range
		{
			get
			{
				return this.range;
			}
			set
			{
				if (this.range != value)
				{
					this.range = value;
					this.OnRangeChanged();
				}
			}
		}
		public virtual Point Position
		{
			get
			{
				return this.range.StartPoint;
			}
			set
			{
				if (this.range.StartPoint != value)
				{
					this.range.StartPoint = value;
					this.range.EndPoint = new Point(value.X + this.name.Length, value.Y);
					this.OnPositionChanged();
				}
			}
		}
		public virtual Size Size
		{
			get
			{
				return new Size(this.range.EndPoint.X - this.range.StartPoint.X, this.range.EndPoint.Y - this.range.StartPoint.Y);
			}
			set
			{
				this.range.EndPoint = new Point(this.range.StartPoint.X + value.Width, this.range.StartPoint.Y + value.Height);
				this.OnSizeChanged();
			}
		}
		public virtual string Name
		{
			get
			{
				return this.name;
			}
			set
			{
				if (this.name != value)
				{
					this.name = value;
					this.OnNameChanged();
				}
			}
		}
		public virtual int NodeType
		{
			get
			{
				return this.nodeType;
			}
			set
			{
				if (this.nodeType != value)
				{
					this.nodeType = value;
					this.OnNodeTypeChanged();
				}
			}
		}
		public virtual SyntaxNode Parent
		{
			get
			{
				return this.parent;
			}
			set
			{
				if (this.parent != value)
				{
					this.parent = value;
					this.OnParentChanged();
				}
			}
		}
		public virtual SyntaxNode Root
		{
			get
			{
				SyntaxNode syntaxNode = this.parent;
				while (syntaxNode != null && syntaxNode.Parent != null)
				{
					syntaxNode = syntaxNode.Parent;
				}
				return syntaxNode;
			}
		}
		public virtual SyntaxNodeOptions Options
		{
			get
			{
				return this.options;
			}
			set
			{
				if (this.options != value)
				{
					this.options = value;
					this.OnOptionsChanged();
				}
			}
		}
		public virtual SyntaxNode[] Childs
		{
			get
			{
				SyntaxNode[] result;
				if (this.childs == null)
				{
					result = new SyntaxNode[0];
				}
				else
				{
					SyntaxNode[] array = new SyntaxNode[this.childs.Count];
					this.childs.CopyTo(array, 0);
					result = array;
				}
				return result;
			}
			set
			{
				if (value == null || value.Length == 0)
				{
					if (this.childs != null)
					{
						this.childs.Clear();
					}
					this.childs = null;
				}
				else
				{
					if (this.childs == null)
					{
						this.childs = new SyntaxNodes();
					}
					this.childs.Clear();
					for (int i = 0; i < value.Length; i++)
					{
						SyntaxNode item = value[i];
						this.childs.Add(item);
					}
				}
				this.OnChildsChanged();
			}
		}
		public virtual SyntaxAttribute[] Attributes
		{
			get
			{
				SyntaxAttribute[] result;
				if (this.attributes == null)
				{
					result = new SyntaxAttribute[0];
				}
				else
				{
					SyntaxAttribute[] array = new SyntaxAttribute[this.attributes.Count];
					this.attributes.CopyTo(array, 0);
					result = array;
				}
				return result;
			}
			set
			{
				if (value == null || value.Length == 0)
				{
					if (this.attributes != null)
					{
						this.attributes.Clear();
					}
					this.attributes = null;
				}
				else
				{
					if (this.attributes == null)
					{
						this.attributes = new SyntaxAttributes();
					}
					this.attributes.Clear();
					for (int i = 0; i < value.Length; i++)
					{
						SyntaxAttribute item = value[i];
						this.attributes.Add(item);
					}
				}
				this.OnAttributesChanged();
			}
		}
		public virtual SyntaxError[] Errors
		{
			get
			{
				SyntaxError[] result;
				if (this.errors == null)
				{
					result = new SyntaxError[0];
				}
				else
				{
					SyntaxError[] array = new SyntaxError[this.errors.Count];
					this.errors.CopyTo(array, 0);
					result = array;
				}
				return result;
			}
			set
			{
				if (value == null || value.Length == 0)
				{
					if (this.errors != null)
					{
						this.errors.Clear();
					}
					this.errors = null;
				}
				else
				{
					if (this.errors == null)
					{
						this.errors = new SyntaxErrors();
					}
					this.errors.Clear();
					for (int i = 0; i < value.Length; i++)
					{
						SyntaxError item = value[i];
						this.errors.Add(item);
					}
				}
				this.OnErrorsChanged();
			}
		}
		public virtual SyntaxNodes ChildList
		{
			get
			{
				return this.childs;
			}
		}
		public virtual SyntaxAttributes AttributeList
		{
			get
			{
				return this.attributes;
			}
		}
		public virtual SyntaxErrors ErrorList
		{
			get
			{
				return this.errors;
			}
		}
		public virtual bool HasChildren
		{
			get
			{
				return this.childs != null && this.childs.Count > 0;
			}
		}
		public virtual bool HasAttributes
		{
			get
			{
				return this.attributes != null && this.attributes.Count > 0;
			}
		}
		public virtual bool HasErrors
		{
			get
			{
				return this.errors != null && this.errors.Count > 0;
			}
		}
		public virtual int Level
		{
			get
			{
				int num = 0;
				SyntaxNode syntaxNode = this.parent;
				while (syntaxNode != null)
				{
					syntaxNode = syntaxNode.Parent;
					num++;
				}
				return num;
			}
		}
		public virtual int ChildCount
		{
			get
			{
				return (this.childs != null) ? this.childs.Count : 0;
			}
		}
		public virtual int AttributeCount
		{
			get
			{
				return (this.attributes != null) ? this.attributes.Count : 0;
			}
		}
		public virtual int ErrorCount
		{
			get
			{
				return (this.errors != null) ? this.errors.Count : 0;
			}
		}
		public virtual int Index
		{
			get
			{
				return (this.parent != null && this.parent.ChildList != null) ? this.parent.ChildList.IndexOf(this) : -1;
			}
		}
		protected virtual void OnRangeChanged()
		{
		}
		protected virtual void OnPositionChanged()
		{
		}
		protected virtual void OnSizeChanged()
		{
		}
		protected virtual void OnNameChanged()
		{
		}
		protected virtual void OnNodeTypeChanged()
		{
		}
		protected virtual void OnParentChanged()
		{
		}
		protected virtual void OnOptionsChanged()
		{
		}
		protected virtual void OnChildsChanged()
		{
		}
		protected virtual void OnAttributesChanged()
		{
		}
		protected virtual void OnErrorsChanged()
		{
		}
		protected bool InsideRange(Point pt, Rectangle rect)
		{
			return Circus.CodeEditor.Range.InsideRange(pt, rect);
		}
		protected bool ContainsErrors(bool recursive)
		{
			bool result;
			if (this.HasErrors)
			{
				result = true;
			}
			else
			{
				if (recursive && this.HasChildren)
				{
					foreach (SyntaxNode current in this.ChildList)
					{
						if (current.ContainsErrors())
						{
							result = true;
							return result;
						}
					}
				}
				result = false;
			}
			return result;
		}
		public SyntaxNode()
		{
		}
		public SyntaxNode(Point position, string name)
		{
			this.range.StartPoint = position;
			this.range.EndPoint = new Point(position.X + name.Length, position.Y);
			this.name = name;
		}
		public SyntaxNode(Point position, string name, int nodeType) : this(position, name)
		{
			this.nodeType = nodeType;
		}
		public SyntaxNode(Point position, string name, int nodeType, SyntaxNodeOptions options) : this(position, name, nodeType)
		{
			this.options = options;
		}
		public override string ToString()
		{
			return (this.name != string.Empty) ? this.name : base.ToString();
		}
		public virtual bool PositionChanged(int x, int y, int deltaX, int deltaY, IComparer<SyntaxNode> comparer)
		{
			bool result = false;
			if (this.HasAttributes && this.attributes.PositionChanged(x, y, deltaX, deltaY))
			{
				result = true;
			}
			if (this.HasErrors && this.errors.PositionChanged(x, y, deltaX, deltaY))
			{
				result = true;
			}
			if (this.HasChildren && this.childs.PositionChanged(x, y, deltaX, deltaY, comparer))
			{
				result = true;
			}
			return result;
		}
		public virtual bool BlockDeleting(Rectangle rect, IComparer<SyntaxNode> comparer)
		{
			bool result = false;
			if (this.HasAttributes && this.attributes.BlockDeleting(rect))
			{
				result = true;
			}
			if (this.HasErrors && this.errors.BlockDeleting(rect))
			{
				result = true;
			}
			if (this.HasChildren && this.childs.BlockDeleting(rect, comparer))
			{
				result = true;
			}
			return result;
		}
		public virtual void Clear()
		{
			this.containsErrors = null;
			if (this.childs != null)
			{
				this.childs.Clear();
			}
			this.childs = null;
			if (this.attributes != null)
			{
				this.attributes.Clear();
			}
			this.attributes = null;
			if (this.errors != null)
			{
				this.errors.Clear();
			}
			this.errors = null;
		}
		public void ClearAfter(Point position)
		{
			if (this.childs != null)
			{
				for (int i = this.childs.Count - 1; i >= 0; i--)
				{
					SyntaxNode syntaxNode = this.childs[i];
					if (syntaxNode.Position.Y > position.Y || (syntaxNode.Position.Y == position.Y && syntaxNode.Position.X >= position.Y))
					{
						this.childs.RemoveAt(i);
					}
				}
			}
			if (this.attributes != null)
			{
				for (int i = this.attributes.Count - 1; i >= 0; i--)
				{
					SyntaxAttribute syntaxAttribute = this.attributes[i];
					if (syntaxAttribute.Position.Y > position.Y || (syntaxAttribute.Position.Y == position.Y && syntaxAttribute.Position.X >= position.Y))
					{
						this.attributes.RemoveAt(i);
					}
				}
			}
			if (this.errors != null)
			{
				for (int i = this.errors.Count - 1; i >= 0; i--)
				{
					SyntaxError syntaxError = this.errors[i];
					if (syntaxError.Position.Y > position.Y || (syntaxError.Position.Y == position.Y && syntaxError.Position.X >= position.Y))
					{
						this.errors.RemoveAt(i);
					}
				}
			}
		}
		public virtual int AddChild(SyntaxNode node)
		{
			if (this.childs == null)
			{
				this.childs = new SyntaxNodes();
			}
			node.Parent = this;
			this.childs.Add(node);
			return this.childs.Count - 1;
		}
		public virtual SyntaxNode AddChild()
		{
			if (this.childs == null)
			{
				this.childs = new SyntaxNodes();
			}
			SyntaxNode syntaxNode = new SyntaxNode();
			syntaxNode.Parent = this;
			this.childs.Add(syntaxNode);
			return syntaxNode;
		}
		public virtual int InsertChild(SyntaxNode node, IComparer<SyntaxNode> comparer)
		{
			int result;
			if (!this.HasChildren)
			{
				result = this.AddChild(node);
			}
			else
			{
				int num;
				this.childs.FindLast(node, out num, comparer);
				this.childs.Insert(num, node);
				node.Parent = this;
				result = num;
			}
			return result;
		}
		public virtual void AddChildren(SyntaxNodes nodes)
		{
			if (this.childs == null)
			{
				this.childs = new SyntaxNodes();
			}
			foreach (SyntaxNode current in nodes)
			{
				current.Parent = this;
				this.childs.Add(current);
			}
		}
		public virtual int AddAttribute(SyntaxAttribute attr)
		{
			if (this.attributes == null)
			{
				this.attributes = new SyntaxAttributes();
			}
			this.attributes.Add(attr);
			return this.attributes.Count - 1;
		}
		public virtual SyntaxAttribute AddAttribute()
		{
			if (this.attributes == null)
			{
				this.attributes = new SyntaxAttributes();
			}
			SyntaxAttribute syntaxAttribute = new SyntaxAttribute();
			this.attributes.Add(syntaxAttribute);
			return syntaxAttribute;
		}
		public virtual void AddAttributes(SyntaxAttributes attrs)
		{
			if (this.attributes == null)
			{
				this.attributes = new SyntaxAttributes();
			}
			foreach (SyntaxAttribute current in attrs)
			{
				this.attributes.Add(current);
			}
		}
		public virtual int AddError(SyntaxError err)
		{
			if (this.errors == null)
			{
				this.errors = new SyntaxErrors();
			}
			this.errors.Add(err);
			return this.errors.Count - 1;
		}
		public virtual SyntaxError AddError()
		{
			if (this.errors == null)
			{
				this.errors = new SyntaxErrors();
			}
			SyntaxError syntaxError = new SyntaxError();
			this.errors.Add(syntaxError);
			return syntaxError;
		}
		public virtual void AddErrors(SyntaxErrors errs)
		{
			if (this.errors == null)
			{
				this.errors = new SyntaxErrors();
			}
			foreach (SyntaxError current in errs)
			{
				this.errors.Add(current);
			}
		}
		public virtual bool HasAsParent(SyntaxNode node)
		{
			bool result;
			for (SyntaxNode syntaxNode = this.parent; syntaxNode != null; syntaxNode = syntaxNode.Parent)
			{
				if (syntaxNode == node)
				{
					result = true;
					return result;
				}
			}
			result = false;
			return result;
		}
		public virtual SyntaxNode FindNode(string name)
		{
			SyntaxNode result;
			if (this.childs != null)
			{
				foreach (SyntaxNode current in this.childs)
				{
					if (current.Name == name)
					{
						result = current;
						return result;
					}
				}
			}
			result = null;
			return result;
		}
		public virtual SyntaxNode FindNode(int nodeType)
		{
			SyntaxNode result;
			if (this.childs != null)
			{
				foreach (SyntaxNode current in this.childs)
				{
					if (current.NodeType == nodeType)
					{
						result = current;
						return result;
					}
				}
			}
			result = null;
			return result;
		}
		public virtual SyntaxNode FindNode(SyntaxNode node, IComparer<SyntaxNode> comparer)
		{
			SyntaxNode result;
			if (this.childs != null)
			{
				int index;
				result = (this.childs.FindLast(node, out index, comparer) ? this.childs[index] : null);
			}
			else
			{
				result = null;
			}
			return result;
		}
		public virtual void FindNodes(SyntaxNode obj, IComparer<SyntaxNode> comparer, SyntaxNodes nodes)
		{
			if (this.childs != null)
			{
				int i;
				if (this.childs.FindFirst(obj, out i, comparer))
				{
					SyntaxNode syntaxNode = this.childs[i];
					nodes.Add(syntaxNode);
					syntaxNode.FindNodes(obj, comparer, nodes);
					for (i++; i < this.childs.Count; i++)
					{
						syntaxNode = this.childs[i];
						if (comparer.Compare(syntaxNode, obj) != 0)
						{
							break;
						}
						nodes.Add(syntaxNode);
						syntaxNode.FindNodes(obj, comparer, nodes);
					}
				}
			}
		}
		public virtual SyntaxAttribute FindAttribute(string name)
		{
			SyntaxAttribute result;
			if (this.attributes != null)
			{
				foreach (SyntaxAttribute current in this.attributes)
				{
					if (current.Name == name)
					{
						result = current;
						return result;
					}
				}
			}
			result = null;
			return result;
		}
		public virtual SyntaxAttribute[] FindAttributes(string name)
		{
			SyntaxAttribute[] result;
			if (this.attributes != null)
			{
				int num = 0;
				foreach (SyntaxAttribute current in this.attributes)
				{
					if (current.Name == name)
					{
						num++;
					}
				}
				SyntaxAttribute[] array = new SyntaxAttribute[num];
				num = 0;
				foreach (SyntaxAttribute current in this.attributes)
				{
					if (current.Name == name)
					{
						array[num] = current;
						num++;
					}
				}
				result = array;
			}
			else
			{
				result = null;
			}
			return result;
		}
		public virtual void Sort(IComparer<SyntaxNode> comparer)
		{
			if (this.childs != null)
			{
				this.childs.Sort(comparer);
				foreach (SyntaxNode current in this.childs)
				{
					current.Sort(comparer);
				}
			}
		}
		public virtual int GetIndent(int index, int indent)
		{
			bool flag;
			return this.GetIndent(index, indent, out flag);
		}
		public virtual int GetIndent(int index, int indent, out bool actualPosition)
		{
			actualPosition = false;
			if ((this.Options & SyntaxNodeOptions.KeepIndentation) != SyntaxNodeOptions.None)
			{
				indent = -1;
			}
			else
			{
				if (indent > 0)
				{
					if (index == this.range.StartPoint.Y)
					{
						if ((this.options & SyntaxNodeOptions.Indentation) == SyntaxNodeOptions.None || (this.options & SyntaxNodeOptions.BackIndentation) == SyntaxNodeOptions.None)
						{
							indent--;
						}
					}
					else
					{
						if (this.HasAttributes)
						{
							foreach (SyntaxAttribute current in this.attributes)
							{
								if ((current.Name == SyntaxConsts.DefinitionScope || current.Name == SyntaxConsts.DefinitionScopeEnd) && current.Position.Y == index)
								{
									indent--;
									break;
								}
							}
						}
					}
				}
			}
			return indent;
		}
		public bool ContainsErrors()
		{
			if (this.containsErrors == null)
			{
				this.containsErrors = this.ContainsErrors(true);
			}
			return (bool)this.containsErrors;
		}
		public virtual void Assign(SyntaxNode source)
		{
			this.Clear();
			this.Range.Assign(source.Range);
			this.Name = source.Name;
			this.NodeType = source.NodeType;
			this.Options = source.Options;
			if (source.HasAttributes)
			{
				SyntaxAttribute[] array = source.Attributes;
				for (int i = 0; i < array.Length; i++)
				{
					SyntaxAttribute syntaxAttribute = array[i];
					this.AddAttribute((SyntaxAttribute)syntaxAttribute.Clone());
				}
			}
			if (source.HasErrors)
			{
				SyntaxError[] array2 = source.Errors;
				for (int i = 0; i < array2.Length; i++)
				{
					SyntaxError syntaxError = array2[i];
					this.AddError((SyntaxError)syntaxError.Clone());
				}
			}
			if (source.HasChildren)
			{
				foreach (SyntaxNode current in source.ChildList)
				{
					this.AddChild((SyntaxNode)current.Clone());
				}
			}
		}
		public virtual object Clone()
		{
			SyntaxNode syntaxNode = new SyntaxNode();
			syntaxNode.Assign(this);
			return syntaxNode;
		}
	}
}
